import { app, BrowserWindow, Menu, ipcMain } from 'electron'
import path from 'node:path'
import { DownloaderHelper } from 'node-downloader-helper'
import fs from "fs-extra"

// The built directory structure
//
// ├─┬─┬ dist
// │ │ └── index.html
// │ │
// │ ├─┬ dist-electron
// │ │ ├── main.js
// │ │ └── preload.js
// │
process.env.DIST = path.join(__dirname, '../dist')
process.env.VITE_PUBLIC = app.isPackaged ? process.env.DIST : path.join(process.env.DIST, '../public')


let win: BrowserWindow | null
// 🚧 Use ['ENV_NAME'] avoid vite:define plugin - Vite@2.x
const VITE_DEV_SERVER_URL = process.env['VITE_DEV_SERVER_URL']

function createWindow() {
  win = new BrowserWindow({
    icon: path.join(process.env.VITE_PUBLIC, 'favicon.ico'),
    width: 1000,
    height: 600,
    minWidth: 900,
    minHeight: 500,
    backgroundColor: "#ffffff",
    titleBarStyle: "hidden",
    titleBarOverlay: {
      color: "rgba(255, 255, 255, 0)",
      symbolColor: "black",
      height: 31,
    },
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    },
  })

  Menu.setApplicationMenu(null);

  createPreload();

  // Test active push message to Renderer-process.
  win.webContents.on('did-finish-load', () => {
    win?.webContents.send('main-process-message', (new Date).toLocaleString())
  })

  if (VITE_DEV_SERVER_URL) {
    win.webContents.openDevTools()
    win.loadURL(VITE_DEV_SERVER_URL)
  } else {
    // win.loadFile('dist/index.html')
    win.loadFile(path.join(process.env.DIST, 'index.html'))
  }
}

function createPreload() {
  ipcMain.handle("start", (_: any, data: any): Promise<any> => {
    return new Promise((resolve, reject) => {
      try {
        const winChild = new BrowserWindow({
          icon: path.join(process.env.VITE_PUBLIC, 'favicon.ico'),
          title: data.title,
          show: false,
          width: data.width || 800,
          height: data.height || 600,
          backgroundColor: "#ffffff",
        })
        let filepath = path.join(__dirname, `${data.name}.asar`)
        if (fs.existsSync(filepath)) {
          winChild.loadFile(path.join(filepath, 'index.html'))
        } else {
          winChild.loadURL(data.url)
        }
        winChild.once('ready-to-show', () => {
          winChild.show()
          resolve({ id: winChild.id })
        })
      } catch (err) {
        console.error(err)
        reject(err)
      }
    })
  })
  ipcMain.handle("modal", (_: any, data: any): Promise<any> => {
    return new Promise((resolve, reject) => {
      try {
        const winChild = new BrowserWindow({
          icon: path.join(process.env.VITE_PUBLIC, 'favicon.ico'),
          title: data.title,
          show: false,
          width: data.width || 800,
          height: data.height || 600,
          resizable: false,
          maximizable: false,
          minimizable: false,
          modal: true,
          parent: win || undefined,
          backgroundColor: "#ffffff",
          webPreferences: {
            preload: path.join(__dirname, 'preload.js'),
          },
        })
        if (VITE_DEV_SERVER_URL) {
          winChild.loadURL(VITE_DEV_SERVER_URL + '/#' + data.url)
        } else {
          winChild.loadFile(path.join(process.env.DIST, 'index.html', "#", data.url))
        }
        winChild.once('ready-to-show', () => {
          winChild.show()
          resolve({ id: winChild.id })
        })
      } catch (err) {
        console.error(err)
        reject(err)
      }
    })
  })
  ipcMain.handle("download", (_: any, data: any): Promise<any> => {
    return new Promise((resolve, reject) => {
      const dl = new DownloaderHelper(data.url, __dirname, { fileName: data.name });
      dl.on('end', () => {
        fs.renameSync(path.join(__dirname, data.name), path.join(__dirname, `${data.name}.asar`))
        resolve("Download Success")
      });
      dl.on('error', (err) => {
        console.error(err)
        reject("Download Failed")
      });
      dl.start().catch((err) => {
        console.error(err)
        reject("Download Error")
      });
    })
  })
  ipcMain.handle("tools", (_: any): Promise<any> => {
    return new Promise((resolve) => {
      let files = fs.readdirSync(__dirname)
      let items = []
      for (let i = 0; i < files.length; i++) {
        if (files[i].endsWith(".asar")) {
          items.push(files[i].replace(".asar", ""))
        }
      }
      resolve(items)
    })
  })
}

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
    win = null
  }
})

app.on('activate', () => {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})

app.whenReady().then(createWindow)
